package com.ruoyi.user.service.impl;


import com.alibaba.fastjson.JSON;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.ruoyi.user.domain.RefundInfo;
import com.ruoyi.user.domain.UserOrder;
import com.ruoyi.user.mapper.RefundInfoMapper;
import com.ruoyi.user.service.IUserOrderService;
import com.ruoyi.user.utils.BigDecimalUtil;
import com.ruoyi.user.utils.DateUtils;
import com.ruoyi.user.utils.PayChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Map;

/**
 * @Discription:
 * @Author: LargeRoc
 * @Date: Create in 2017/10/23 17:15
 * @Modified By:
 * @Modified Date:
 */
@Service("refundInfoService")
@Transactional(rollbackFor = Exception.class)
public class RefundInfoService {
    @Autowired
    private RefundInfoMapper refundInfoMapper;
    @Autowired
    private IUserOrderService userOrderService;

    /**
     * 退款金额：元
     *
     * @param orderId
     * @param refundType
     * @return
     */
    public BigDecimal searchRefundSumPayByOrderId(String orderId, String refundType) {
        return refundInfoMapper.searchRefundSumPayByOrderId(orderId, refundType);
    }

    /**
     * 微信app支付的退款通知
     *
     * @param resultMap
     */
    @Transactional(rollbackFor = Exception.class)
    public void refundForWxNativeNotice(Map<String, String> resultMap) {
        refundForWxNotice(resultMap);
    }

    /**
     * 通过退款id 查询退款记录
     *
     * @param refundId
     * @return
     */
    public RefundInfo searchRefundInfoByRefundId(String refundId) {
        return refundInfoMapper.searchRefundInfoByRefundId(refundId);
    }

    /**
     * 保存退款记录信息
     *
     * @param refundInfo
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateRefundInfo(RefundInfo refundInfo) {
        if (refundInfo.getId() == null) {
            refundInfoMapper.save(refundInfo);
        } else {
            refundInfoMapper.update(refundInfo);
        }
    }

    /**
     * 调用微信退款api后，进行保存退款处理记录
     * 如果有红包抵扣金额，就直接给红包金额返还
     */
    @Transactional(rollbackFor = Exception.class)
    public void afterCallingwxRefundApiSaveRefundInfo(RefundInfo refundInfo) {
        saveOrUpdateRefundInfo(refundInfo);
    }


    /**
     * 微信退款的通知，包括原生支付退款及小程序支付退款，微信公众号退款
     *
     * @param resultMap
     */
    @Transactional(rollbackFor = Exception.class)
    public void refundForWxNotice(Map<String, String> resultMap) {
        String refundId = resultMap.get("out_refund_no");
        RefundInfo refundInfo = searchRefundInfoByRefundId(refundId);
        UserOrder order = userOrderService.findOrderByOrderId(refundInfo.getOrderId());
        BigDecimal sumPay = refundInfoMapper.searchRefundSumPayByOrderId(order.getOrderId(), order.getChannel());
        /**
         * 一次性全额退款
         */
        BigDecimal refundAmount = BigDecimal.valueOf(refundInfo.getAmount()).divide(BigDecimal.valueOf(100)).setScale(2);
        if (order.getNeedPayTotalFee().compareTo(refundAmount) == 0) {
            order.setStatus(PayChannel.TransactionStatus.REFUNDSUCCESS.getValue());
        }
        /**
         * 多次退款 全额退款
         */
        else if (order.getNeedPayTotalFee().compareTo(BigDecimalUtil.add(refundAmount, sumPay)) == 0 && sumPay.compareTo(BigDecimal.ZERO) > 0) {
            order.setStatus(PayChannel.TransactionStatus.REFUNDSUCCESS.getValue());
        } else {
            order.setStatus(PayChannel.TransactionStatus.PARTIALREFUNDSUCCESS.getValue());
        }
        userOrderService.updateUserOrder(order);
        //退款金额 分
        Integer settlementRefundFee = Integer.valueOf(resultMap.get("settlement_refund_fee"));
        refundInfo.setOutRequestNo(resultMap.get("refund_id"));
        refundInfo.setPay(BigDecimal.valueOf(settlementRefundFee).divide(BigDecimal.valueOf(100)).setScale(2));
        refundInfo.setStatus(PayChannel.RefundStatus.SUCCEEDED.getValue());
        refundInfo.setSucceed(true);
        if (resultMap.get("success_time") != null) {
            String wxXcxRefundSuccessDate = resultMap.get("success_time");
            Long successTime = DateUtils.str2Long(wxXcxRefundSuccessDate, DateUtils.PATTERN_1);
            refundInfo.setTimeSucceed(successTime);
        } else {
            refundInfo.setTimeSucceed(System.currentTimeMillis());
        }
        refundInfo.setReponseResult(JSON.toJSONString(resultMap));
        saveOrUpdateRefundInfo(refundInfo);
    }


    /**
     * 支付宝退款
     *
     * @param order
     * @param refundInfo
     * @param refundResponse
     */
    @Transactional(rollbackFor = Exception.class)
    public void refundForAliPay(UserOrder order, RefundInfo refundInfo, AlipayTradeRefundResponse refundResponse) {
        updateOrderRefundStatus(order, refundInfo);
        userOrderService.updateUserOrder(order);
        refundInfo.setTradeNo(refundResponse.getTradeNo());
        refundInfo.setOutRequestNo(refundInfo.getRefundId());
//        支付宝返回的是累计退款金额
//        refundInfo.setPay(BigDecimal.valueOf(refundResponse.getRefundFee()));
        refundInfo.setPay(BigDecimal.valueOf(refundInfo.getAmount()).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
        refundInfo.setStatus(PayChannel.RefundStatus.SUCCEEDED.getValue());
        refundInfo.setSucceed(true);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String aliPayRefundSuccessDate = sdf.format(refundResponse.getGmtRefundPay());
        Long successTime = DateUtils.str2Long(aliPayRefundSuccessDate, DateUtils.PATTERN_1);
        refundInfo.setTimeSucceed(successTime);
        refundInfo.setReponseResult(JSON.toJSONString(refundResponse));
        saveOrUpdateRefundInfo(refundInfo);
    }

    /**
     * 判断 订单是部分退款还是全额退款
     *
     * @param order
     * @param refundInfo
     */
    private void updateOrderRefundStatus(UserOrder order, RefundInfo refundInfo) {
        BigDecimal sumPay = refundInfoMapper.searchRefundSumPayByOrderId(order.getOrderId(), order.getChannel());
        /**
         * 一次性全额退款
         */
        BigDecimal refundAmount = BigDecimal.valueOf(refundInfo.getAmount()).divide(BigDecimal.valueOf(100)).setScale(2);
        if (order.getNeedPayTotalFee().compareTo(refundAmount) == 0) {
            order.setStatus(PayChannel.TransactionStatus.REFUNDSUCCESS.getValue());
        }
        /**
         * 多次退款 全额退款
         */
        else if (order.getNeedPayTotalFee().compareTo(refundAmount.add(sumPay)) == 0 && sumPay.compareTo(BigDecimal.ZERO) > 0) {
            order.setStatus(PayChannel.TransactionStatus.REFUNDSUCCESS.getValue());
        } else {
            order.setStatus(PayChannel.TransactionStatus.PARTIALREFUNDSUCCESS.getValue());
        }
    }
}